/**
 * 前端使用的所有Api，包括服务器端调用及前端的界面功能和图片
 * 处理功能
 */
import {
    Base
} from "./base"; // 调用服务端请求的Api
import {
    Config
} from "./config"; // Api服务地址
import {
    Utils
} from "./util";

/** 证件照*/
class IDPhotoParam {

}

class MatchApi extends Base {
    //调用基类构造函数初始化必要参数
    constructor() {
        super();
    }
    /**加载所有数据存入缓存 */
    getAllDataFromServer() {
        let params = {
            url: Config.stListUrl,
        };
        MatchApi.request(params).then(data => {
            wx.setStorageSync('alldata', data);
            var data = wx.getStorageSync('alldata');
        },err=>{
            reject(err)
        })
    }
    /** 获取证件照尺寸 */
    getAllSizes() {
        // 设置参数
        let params = {
            url: Config.sizeListUrl,
        };

        return MatchApi.request(params);
    }
    /** 获取证件照尺寸类型 */
    getAllSizeTypes() {
        // 设置参数
        let params = {
            url: Config.stListUrl,
        };
        return Base.request(params);

    }
    /** 获取背景色 */
    getAllBgs() {
        // 设置参数
        let params = {
            url: Config.bgListUrl,
        };
        return Base.request(params);
    }
    /**图片风格化 */
    getAnimeImage(fileName,algo){
        
        let params = {
            url: Config.animeUrl,
            type:'post',
            data:{
                image_url:fileName,
                algo:algo
            }
        }
        return Base.request(params)
    }
    /**获取上传签名，同时返回访问地址 */
    getUploadSignature(fileName) {
        let params = {
            url: Config.uploadSignature,
            type:'post',
            data:{
                filename:fileName
            }
        }
        return Base.request(params)
    }
    /**
     * 人像人体分割
     * @param {待分割图片地址} url 
     * @returns 
     */
    segmentBody(url) {
        let params = {
            url: Config.segmentBodyUrl,
            type: 'POST',
            data: {
                image_url: url
            }
        }
        return Base.request(params);
    }
    /**
     * 分割人像头部并返回头部位置
     * @param {*} url 
     * @returns 
     */
    segmentHead(url) {
        return new Promise((resolve, reject) => {
            let params = {
                url: Config.segmentHeadUrl,
                type: 'POST',
                data: {
                    'image_url': url
                }
            }
            Base.request(params).then(res => {
                // 对可能存在多个头像信息的情况,计算所有
                // 头像的位置信息
                let headInfo = this.computeHeadInfo(res.Elements);
                resolve(headInfo);
            }, err => {
                reject(err);
            })
        })
    }
    // 获取头部信息
    headInfo(url){
        let params = {
            url: Config.headInfoUrl,
            type: 'POST',
            data: {
                image_url: url
            }
        }
        return Base.request(params);
    }
    /**
     * 获取广告信息
     * @param {*} url 
     * @returns 
     */
    getAd(position = "") {
        let params = {
            url: Config.adUrl +( position != '' ? "?position=" + position:""),
        }
        return Base.request(params);
    }
    /**小程序配置 */
    getMiniConfig() {
        let params = {
            url: Config.mpConfigUrl,
        }
        return Base.request(params);
    }

    /**
     * 脸部位置以及眼睛中心点位置检测
     * @param {url} url 
     */
    detectFace(url) {
        return new Promise((resolve, reject) => {
            let params = {
                url: Config.detectFaceUrl,
                type: 'POST',
                data: {
                    'image_url': url
                }
            }
            Base.request(params).then(res => {
                // 对可能存在多个头像信息的情况,计算所有
                // 头像的位置信息
                // let headInfo = this.computeHeadInfo(res.DataData);

                resolve(res.Face);
            }, err => {
                reject(err);
            })
        })
    }

    /** 获取服务产品信息 */
    getProductPrice() {
        let params = {
            url: Config.productGetUrl,
        }
        return Base.request(params);
    }

    /** 生成证件照相关函数 */
    /** 创建证件照 */
    createIDPhoto(canvas, imgSrc, photoSize) {

        return new Promise((resolve, reject) => {
            //压缩后图片Url地址
            let ossImgUrl = null;
            let tempFile = null;
            // 压缩图片

            this.compressImage(canvas, imgSrc, 1279, 1279).then(res => {
                let fileParam = {
                    name: Utils.getUuid(4, 3) + Utils.getFileType(res),
                    src: res
                }
                return this.uploadFile(fileParam); // 上传文件
            }).then(async res => {
                ossImgUrl = res;
                // console.log("ossImgUrl",ossImgUrl)
                //获取头部位置信息
                const headInfo = await this.headInfo(ossImgUrl);
                const faceRect = [headInfo.FaceRect.left,headInfo.HeadTop,headInfo.FaceRect.right-headInfo.FaceRect.left,headInfo.FaceRect.bottom];

                // 修改头顶坐标为包含头发的坐标
                const info = {
                    "EyeCenter": headInfo.EyeCenter,
                    "FaceRectangle": faceRect
                };
                return new Promise((resolve, reject) => {
                    resolve(info);
                });
            }).then(headInfo => {
                // console.log("headInfo2",headInfo)
                // 计算 从图片上裁剪证件照的位置
                let cropInfo = this.getSrcCopperBox(photoSize, headInfo);
                // console.log("cropinfo:",cropInfo)
                return this.cropImageBySize(canvas, ossImgUrl, cropInfo, photoSize);
            }).then(src => {
                // console.log("cropImageBySize",src)
                let fileParam = {
                    name: Utils.getUuid(4, 3) + Utils.getFileType(src),
                    src: src
                }
                return this.uploadFile(fileParam);
            }).then(res => {
                // console.log("uploadFile2",res)
                return this.segmentBody(res);

            }).then(res => {
                // console.log("segmentBody2",res)
                return this.getImageTempUrl(res.ImageURL);
            }).then(res => {
                // console.log("getImageTempUrl",res)
                let result = {
                    width: photoSize.width,
                    height: photoSize.height,
                    wpx: Utils.getPixel(photoSize.width, photoSize.dpi),
                    hpx: Utils.getPixel(photoSize.height, photoSize.dpi),
                    image: res.tmpUrl,
                    // temp:tempFile
                }
                resolve(result);
            }).catch(err=>{
                reject(err)
            })
        })
    }

    /** 压缩图片 */
    compressImage(canvasComp, imgSrc, width, height, quality = 1) {
        return new Promise(async (resolve, reject) => {

            let resizeImg = await this.resizeImage(canvasComp, imgSrc, width, height, quality);
            // 获取jpg图片文件大小
            wx.getImageInfo({
                src: resizeImg,
                success(info) {
                    // console.log("resizeImg",resizeImg)
                    resolve(resizeImg);
                },
                fail(err) {
                    reject(err);
                }
            })

        })
    }
    /**压缩图片, 裁剪图片到指定像素大小 */
    resizeImage(canvasComp, imgSrc, width, height, quality = 1) {
        return new Promise((resolve, reject) => {
            // 获取图片尺寸
            wx.getImageInfo({
                src: imgSrc,
                success(info) {
                    // 计算画布设置尺寸
                    let ratio = Math.min(Math.min(width, 1000) / info.width, Math.min(height, 1000) / info.height);
                    let canvasWidth = info.width * ratio;
                    let canvasHeight = info.height * ratio;
                    // console.log("resize",canvasWidth,canvasHeight)
                    // 设置canvas宽度和高度,并进行缩放绘制
                    canvasComp.setSize(canvasWidth, canvasHeight);
                    canvasComp.draw((canvas, ctx, dpi) => {
                        // console.log("canvas draw",canvas)
                        Utils.createImage(canvas, info.path).then(img => {
                            // console.log("createimage,",img)
                            ctx.drawImage(img, 0, 0, info.width, info.height, 0, 0, canvasWidth, canvasHeight);

                            // 导出图片
                            canvasComp.getImageUrl("jpg", quality).then(res => {
                                // console.log("resize,",res)
                                resolve(res);
                            })

                        });
                    });
                },
                fail(err) {
                    reject(err);
                }
            })

        })
    }
    /** 上传图片到oss存储 */
    uploadFile(imgFile) {
        // 获取上传签名
        return new Promise((resolve, reject) => {
            this.getUploadSignature(imgFile.name).then(res => {
                let downloadUrl = res.downloadUrl;
                let signature = res.Signature;
                wx.uploadFile({
                    url: signature.host,
                    //小程序本地的路径
                    filePath: imgFile.src,
                    //后台获取我们图片的key
                    fileType: 'image',
                    name: 'file',
                    //额外的参数formData
                    formData: {
                        Key: signature.dir,
                        Policy: signature.policy,
                        OSSAccessKeyId: signature.accessid,
                        Signature: signature.signature,
                        Success_Action_Status: '200'
                    },
                    success: function (res) {
                        if (res.statusCode === 200) {
                            resolve(downloadUrl)
                        } else {
                            reject(res);
                        }
                    },
                    fail: function (err) {
                        reject(err)
                    },
                })
            },err=>{
                reject(err)
            })
        })

    }
    /** 计算头部位置,可能存在多个人像,所以要计算所有头像占的区域位置 */
    computeHeadInfo(headInfo) {
        let leftArr = [];
        let rightArr = [];
        let topArr = [];
        let bottomArr = [];

        headInfo.forEach(element => {
            leftArr.push(element.X);
            rightArr.push(element.X + element.Width);
            topArr.push(element.Y);
            bottomArr.push(element.Y + element.Height);

        });
        let minX = Math.min(...leftArr);
        let minY = Math.min(...topArr);
        let maxW = Math.max(...rightArr) - minX;
        let maxH = Math.max(...bottomArr) - minY;

        return {
            'X': minX,
            'Y': minY,
            'Width': maxW,
            'Height': maxH
        }
    }

    /**
     * /根据证件照尺寸计算在图片上裁剪证件照尺寸的裁剪框
     * @param {*} idphotoSize 
     * @param {*} srcHeadInfo 结构
     * {"EyeCenter": {
            "x": 460,
            "y": 376
        },
        "FaceRectangles": [
            355,
            122,
            213,
            274
        ]}
     */
    getSrcCopperBox(idphotoSize, srcHeadInfo) {

        // 证件照的像素尺寸
        let width = Utils.getPixel(idphotoSize.width, idphotoSize.dpi);
        let height = Utils.getPixel(idphotoSize.height, idphotoSize.dpi);
        let top = Utils.getPixel(idphotoSize.top_dis, idphotoSize.dpi);
        let edge = Utils.getPixel(idphotoSize.edge_dis, idphotoSize.dpi);


        top = Math.max(20, Math.min(40, top))
        // 证件照头部宽度
        let idphotoHeadWidth = width - 2 * edge;

        // 原始照片脸部宽度,需要调整为包括耳朵的头部宽度
        const srcHeadWidth = srcHeadInfo.FaceRectangle[2] * 1.3;
        // 眼睛中心坐标
        const eyeCenter = srcHeadInfo.EyeCenter;
        //实际头部宽度与证件照头部宽度比例
        let ratio = srcHeadWidth / idphotoHeadWidth;
        let copperX = Math.round(eyeCenter.x - width / 2 * ratio);
        let copperY = srcHeadInfo.FaceRectangle[1];
        // // 眼睛至底部的最小距离不能小于207像素
        if (((copperY + Math.round((height - top) * ratio) - eyeCenter.y) / ratio) < 207) {
            // 如果小于207像素,则重新计算copperY
            copperY = eyeCenter.y - (height - top - 207) * ratio;
        }

        let copperWidth = Math.round(width * ratio);
        let copperHeight = Math.round((height - top - 3) * ratio);

        let copperInfo = {
            X: copperX,
            Y: copperY,
            Width: copperWidth,
            Height: copperHeight,
            Top: top
        }
        return copperInfo;
    }
    /** 根据计算的裁剪框位置信息,裁剪原图片,并缩放到证件照尺寸输出 */
    cropImageBySize(canvasComp, imgSrc, cropInfo, photoSize) {
        return new Promise((resolve, reject) => {
            // 创建离屏canvas
            // 根据证件照尺寸计算画布width和height
            let width = Utils.getPixel(photoSize.width, photoSize.dpi);
            let height = Utils.getPixel(photoSize.height, photoSize.dpi);
            canvasComp.setSize(width, height);

            canvasComp.draw((canvas, ctx, dpi) => {

                // 设置背景
                ctx.fillStyle = "green";
                ctx.fillRect(0, 0, width, height);
                Utils.createImage(canvas, imgSrc).then(img => {
                    // 绘制图片
                    ctx.drawImage(img, cropInfo.X, cropInfo.Y, cropInfo.Width, cropInfo.Height,
                        0, cropInfo.Top, width, height - cropInfo.Top);
                    // 导出绘制后的图片
                    canvasComp.getImageUrl().then(res => {
                        resolve(res);
                    }, err => {
                        reject(err);
                    });
                });

            });

        })
    }
    /** 将网络图片保存为本地路径 */
    getImageTempUrl(url) {
        return new Promise((resolve, reject) => {
            url = url.replace("http://","https://")　
            wx.downloadFile({
                url: url,
                success(res) {
                    //   imagesBg = res.tempFilePath
                    resolve({
                        tmpUrl: res.tempFilePath
                    })
                },
                fail(err) {
                    reject(err);
                }
            })

        })
    }


    /**
     * 
     * @param {待添加背景的图片} srcImg 
     * @param {背景色或图片} bg 
     * @param {0:背景为颜色，1：背景为图片} type 
     */
    drawBackground(canvasComp, srcImg, bg, bg2 = -1, type = 0) {
        return new Promise((resolve, reject) => {

            Utils.getImgInfo(srcImg).then(res => {
                canvasComp.setSize(res.width, res.height);
                canvasComp.draw(async (canvas, ctx, dpi) => {
                    //填充背景色
                    if (type == 0) {
                        if (!bg2 || bg2 == -1 || bg2 == 0) {
                            bg2 = bg;
                        }
                        var clg = ctx.createLinearGradient(0, 0, 0, res.height);
                        clg.addColorStop(0, bg); // 第一个参数可以设定渐变位置 数字0~1之间
                        clg.addColorStop(0.6, bg2);

                        ctx.fillStyle = clg;

                        ctx.fillRect(0, 0, res.width, res.height);
                    } else {
                        //填充图片背景
                        let imgBg = await Utils.createImage(canvas, bg);
                        ctx.drawImage(imgBg, 0, 0, imgBg.width, imgBg.height, 0, 0, res.width, res.height);
                    }
                    //填充前景图片
                    let img = await Utils.createImage(canvas, res.path);
                    ctx.drawImage(img, 0, 0);
                    // 导出图片
                    canvasComp.getImageUrl().then(res => {
                        resolve(res);
                    })
                })

            }, err => {
                reject(err);
            })
        })

    }

    /** 更换图片背景 */
    // 更换照片背景
    changeIdphotoBg(canvasComp, imgSrc) {
        return new Promise((resolve, reject) => {
            //压缩图片
            this.compressImage(canvasComp, imgSrc, 1279, 1279).then(res => {
                let fileParam = {
                    name: Utils.getUuid(4, 3) + Utils.getFileType(imgSrc),
                    src: res
                }
                //上传图片
                return this.uploadFile(fileParam);
            }).then(res => {
                //分割图片获取头部位置信息
                return this.segmentBody(res);
            }).then(res => {
                return this.getImageTempUrl(res.ImageURL);
            }).then(res => {
                let imgUrl = res.tmpUrl;
                resolve(imgUrl);
            }, err => {
                reject(err);
            }).catch(err=>{
                reject(err)
            })
        })
    }

    /**
     * 为图片增加水印
     * @param {*} canvasComp 
     * @param {*} srcImg 
     * @param {*} water_img 
     */
    drawWater(canvasComp, srcImg, waterPic, waterText) {
        return new Promise((resolve, reject) => {

            Utils.getImgInfo(srcImg).then(res => {
                canvasComp.setSize(res.width, res.height);
                canvasComp.draw(async (canvas, ctx, dpi) => {
                    //填充前景图片
                    let img = await Utils.createImage(canvas, res.path);
                    ctx.drawImage(img, 0, 0);
                    if (waterPic != '') {
                        //图片水印
                        // 处理本地路径,本地路径许哟啊以"//"开头
                        let firstLeter = waterPic.charAt(0);
                        if (firstLeter == "/") {
                            waterPic = '//' + waterPic.slice(1);
                        }
                        let waterImg = await Utils.createImage(canvas, waterPic);

                        // 水印图片大小为原图宽度的1/3
                        let wh = res.width / 2;
                        let x = res.width - wh;
                        let y = res.height - wh;
                        ctx.drawImage(waterImg, x, y, wh, wh);

                    } else {

                        // 文字水印
                        ctx.save();
                        let str = waterText;
                        ctx.rotate(-25 * Math.PI / 180);
                        let n = Math.round(res.width / 300);
                        ctx.font = n * 20 + "px microsoft yahei";
                        ctx.fillStyle = "rgba(255,255,255,0.3)";
                        ctx.strokeStyle = "rgba(0,0,0,0.3)";
                        ctx.textAlign = 'center';
                        ctx.textBaseline = 'Middle';

                        for (let i = -res.width; i < res.width * 2; i += n * 160) {
                            for (let j = 0; j < res.height * 1.5; j += n * 60) {
                                // ctx.strokeText(str,i,j);
                                ctx.fillText(str, i, j);
                            }
                        }
                        ctx.restore();
                    }


                    // 导出
                    canvasComp.getImageUrl().then(res => {
                        resolve(res);
                    })


                })

            }, err => {
                reject(err);
            })

        })
    }

    /** 支付 */
    // 支付函数获取支付参数
    getPayInfo(payInfo) {
        // 设置参数
        let params = {
            url: Config.payUrl,
            type: 'POST',
            data: payInfo,
        };
        return Base.request(params);
    }

    buySoftWare(payInfo) {

        // 设置参数
        let params = {
            url: Config.paySoftWareUrl,
            type: 'POST',
            data: payInfo,
        };
        return Base.request(params);
    }

    /**保存图片并修改dpi */
    changeDpi(src, dpi) {
        return new Promise((resolve, reject) => {
            // 修改dpi
            let base64Img = Utils.changeJpegDPI(src, dpi);
            this.base64ToUrl(base64Img).then(res => {
                resolve(res);
            },err=>{
                reject(err)
            })

        })
    }

    base64ToUrl(base64Img) {
        return new Promise((resolve, reject) => {
            const dataSplitted = base64Img.split(',');
            if (dataSplitted.length > 1) {
                base64Img = dataSplitted[1];
            }
            // 判断要写入的文件夹是否存在不存在则创建
            let tempFile = `${wx.env.USER_DATA_PATH}` + '/' + Utils.getUuid(4, 3) + '.jpg';
            let fs = wx.getFileSystemManager();
            fs.writeFile({
                filePath: tempFile,
                data: base64Img,
                encoding: 'base64',
                success() {
                    wx.getImageInfo({
                        src: tempFile,
                        success(res) {
                            resolve(res.path);
                        }
                    })
                },
                fail: err => {
                    reject(err);
                }
            })
        })
    }



}
const API = new MatchApi();
export {
    API
};